package com.ukefu.webim.util.impl;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.ansj.domain.Term;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.QueryStringQueryBuilder;
import org.elasticsearch.index.query.QueryStringQueryBuilder.Operator;
import org.jsoup.Jsoup;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Component;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.ukefu.core.UKDataContext;
import com.ukefu.util.UKTools;
import com.ukefu.util.ai.AiUtils;
import com.ukefu.util.ai.DicSegment;
import com.ukefu.util.extra.DataExchangeInterface;
import com.ukefu.webim.service.es.TopicRepository;
import com.ukefu.webim.service.repository.ChatMessageRepository;
import com.ukefu.webim.util.OnlineUserUtils;
import com.ukefu.webim.util.event.AiMessageAskProcesser;
import com.ukefu.webim.util.server.message.ChatMessage;
import com.ukefu.webim.util.server.message.OtherMessageItem;
import com.ukefu.webim.web.model.AiConfig;
import com.ukefu.webim.web.model.AiUser;
import com.ukefu.webim.web.model.KnowledgeType;
import com.ukefu.webim.web.model.Topic;

@Component
public class AiMessageAskProcesserImpl implements AiMessageAskProcesser{
	private ObjectMapper objectMapper = new ObjectMapper();
	@Autowired
	private TopicRepository topicRes ;
	
	@Override
	public ChatMessage process(ChatMessage message , AiMRoundsProcesserImpl aiMroundsProcesser , AiUser aiUser) {
		ChatMessage retChatMessage = null ;
		if(!StringUtils.isBlank(message.getUserid())){
			AiConfig aiConfig = AiUtils.initAiConfig(message.getAiid() , message.getOrgi()) ;
			BoolQueryBuilder boolQueryBuilder = createSearchQuery(message.getOrgi(), message.getAiid()) , subQueryBuilder = QueryBuilders.boolQuery() , titleBoolQueryBuilder = QueryBuilders.boolQuery() ,  mltBoolQueryBuilder = QueryBuilders.boolQuery() ;
			try {
				String[] tokens = null ;
				StringBuffer strb = new StringBuffer();
				Map<String,String> maps = new HashMap<String,String>();
				if(!StringUtils.isBlank(message.getMediaid())) {
					boolQueryBuilder.must(QueryBuilders.termQuery("id", message.getMediaid())) ;
				}else{
					String[] userDefine = DicSegment.busstype(message.getMessage().replaceAll("[\\pP\\p{Punct}]", " "), 100) ;
					if(userDefine!=null && userDefine.length > 0) {
						OnlineUserUtils.procesBussType(aiUser, StringUtils.join(userDefine , ","), aiConfig);
					}
					
					String[] keywords = null ;
					boolean hasUserDefine = false , hasTopic = false ; 
					int keywordNum = 0 ;
					if(aiConfig.isEnablekeyword() && aiConfig.getKeywordnum() > 0){
						if(userDefine!=null && userDefine.length > 0) {
							if(hasUserDefine = hasKeyWord(userDefine)) {
								strb.append("自定义关键词：");
								for(int i=0 ; i<userDefine.length && i<aiConfig.getKeywordnum() ; i++){
									String keyword =  userDefine[i] ;
									if(keyword.length() > 1 && maps.containsKey(keyword) == false) {
										keywordNum++;
										maps.put(keyword, keyword) ;
										strb.append(keyword).append(",") ;
										titleBoolQueryBuilder.should(new QueryStringQueryBuilder("\""+keyword+"\"").field("title").boost(aiConfig.getUserdefinescore() * aiConfig.getTitlescore()).defaultOperator(Operator.AND)) ;
										mltBoolQueryBuilder.should(new QueryStringQueryBuilder("\""+keyword+"\"").field("silimar").boost(aiConfig.getUserdefinescore() * aiConfig.getSilimarscore()).defaultOperator(Operator.AND).useDisMax(true)) ;
									}
								}
								strb.append("\n") ;
							}
						}
						if(keywordNum < aiConfig.getKeywordnum()) {
							String[] topicKeyword = DicSegment.aitopickeyword(message.getMessage().replaceAll("[\\pP\\p{Punct}]", " ") , aiConfig.getKeywordnum() - userDefine.length);
							
							if(topicKeyword!=null && topicKeyword.length > 0) {
								if(hasTopic = hasKeyWord(topicKeyword)) {
									strb.append("主题关键词：");
									for(int i=0 ; i<topicKeyword.length && i<(aiConfig.getKeywordnum() - keywordNum) ; i++){
										String keyword =  topicKeyword[i] ;
										if(keyword.length() > 1 && maps.containsKey(keyword) == false) {
											keywordNum++;
											strb.append(keyword).append(",") ;
											maps.put(keyword, keyword) ;
											titleBoolQueryBuilder.should(new QueryStringQueryBuilder("\""+keyword+"\"").field("title").boost(aiConfig.getTopicscore() * aiConfig.getTitlescore()).defaultOperator(Operator.AND)) ;
											mltBoolQueryBuilder.should(new QueryStringQueryBuilder("\""+keyword+"\"").field("silimar").boost(aiConfig.getTopicscore() * aiConfig.getSilimarscore()).defaultOperator(Operator.AND).useDisMax(true)) ;
										}
									}
									strb.append("\n") ;
								}
							}
						}
						if(aiConfig.isEntity() && !StringUtils.isBlank(aiConfig.getEntitytp())) {
							strb.append("实体识别：");
							List<Term> terms = DicSegment.nsegment(message.getMessage().replaceAll("[\\pP\\p{Punct}]", " ")) ;
							for(Term term : terms) {
								String[] tps = aiConfig.getEntitytp().split(",") ; 
								if(ArrayUtils.contains(tps , "ukefu"+term.getNatureStr()) && (keywordNum < aiConfig.getKeywordnum())) {
									keywordNum++;
									strb.append(term.getName()).append("/").append("ukefu"+term.getNatureStr()).append(",") ;
									titleBoolQueryBuilder.should(new QueryStringQueryBuilder("\"ukefu"+term.getNatureStr()+"\"").field("title").boost(aiConfig.getEntityscore() * aiConfig.getTitlescore()).defaultOperator(Operator.AND)) ;
									mltBoolQueryBuilder.should(new QueryStringQueryBuilder("\"ukefu"+term.getNatureStr()+"\"").field("silimar").boost(aiConfig.getEntityscore() * aiConfig.getSilimarscore()).defaultOperator(Operator.AND).useDisMax(true)) ;
								}
							}
							strb.append("\n") ;
						}
						if(keywordNum < aiConfig.getKeywordnum()) {
							keywords = DicSegment.aikeyword(message.getMessage().replaceAll("[\\pP\\p{Punct}]", " ") , aiConfig.getKeywordnum() - keywordNum);
						}
					}
	
					if(keywords!=null && keywords.length > 0 && hasKeyWord(keywords)){
						strb.append("识别关键词：") ;
						for(int i=0 ; i<keywords.length ; i++){
							String keyword =  keywords[i] ;
							if(keyword.length() > 1 && maps.containsKey(keyword) == false) {
								keywordNum++;
								maps.put(keyword, keyword) ;
								strb.append(keyword).append(",") ;
								titleBoolQueryBuilder.should(new QueryStringQueryBuilder("\""+keyword+"\"").field("title").boost(aiConfig.getKeywordscore() * aiConfig.getTitlescore()).defaultOperator(Operator.AND)) ;
								mltBoolQueryBuilder.should(new QueryStringQueryBuilder("\""+keyword+"\"").field("silimar").boost(aiConfig.getKeywordscore() * aiConfig.getSilimarscore()).defaultOperator(Operator.AND).useDisMax(true)) ;
							}
						}
						strb.append("\n") ;
						subQueryBuilder.should(titleBoolQueryBuilder).should(mltBoolQueryBuilder) ;
					}else if((hasUserDefine == false && hasTopic == false) || keywordNum == 0){
						tokens = DicSegment.aisegment(message.getMessage().replaceAll("[\\pP\\p{Punct}]", " "));
						strb.append("分词：").append(StringUtils.join(tokens , ",")).append("\n") ;
						if(tokens!=null && tokens.length > 0){						
							if(aiConfig.isEnablekeyword() && aiConfig.getKeywordnum() == 0) {
								titleBoolQueryBuilder.should(new QueryStringQueryBuilder(StringUtils.join(tokens , " ")).field("title").boost(0.1f).defaultOperator(Operator.AND)) ;
								mltBoolQueryBuilder.should(new QueryStringQueryBuilder(StringUtils.join(tokens , " ")).field("silimar").boost(0.1f).defaultOperator(Operator.AND).useDisMax(true)) ;
								subQueryBuilder.should(titleBoolQueryBuilder).should(mltBoolQueryBuilder) ;
							}else {
								for(String token : tokens){
									if(!ArrayUtils.contains(keywords, token)){
										titleBoolQueryBuilder.must(new QueryStringQueryBuilder("\""+token+"\"").field("title").boost(0.1f).defaultOperator(Operator.AND)) ;
										mltBoolQueryBuilder.must(new QueryStringQueryBuilder("\""+token+"\"").field("silimar").boost(0.1f).defaultOperator(Operator.AND).useDisMax(true)) ;
									}
								}
								subQueryBuilder.should(titleBoolQueryBuilder).should(mltBoolQueryBuilder) ;
							}
						}
					}else if(hasUserDefine == true || hasTopic == true){
						subQueryBuilder.should(titleBoolQueryBuilder).should(mltBoolQueryBuilder) ;
					}
					
					if(keywordNum > 0 || (tokens!=null && tokens.length > 0)){
						boolQueryBuilder.must(subQueryBuilder) ;
					}else {
						boolQueryBuilder.must(QueryBuilders.termQuery("id", "NOT_EXIST")) ;
					}
				}
				
				/**
				 * 在有效期内
				 */
				Page<Topic> result = topicRes.getTopicByCon(boolQueryBuilder, 0, 5) ;

				List<Topic> topicList = null ;
				/**
				 * 查找按地区问答
				 */
				if(aiUser!=null){
					List<KnowledgeType> topicTypeList = OnlineUserUtils.topicType(message.getOrgi(),aiUser.getIpdata(),OnlineUserUtils.cacheHotTopicType((DataExchangeInterface) UKDataContext.getContext().getBean("topictype") ,null, message.getOrgi() , message.getAiid())) ;
					topicList = OnlineUserUtils.topic(message.getOrgi(), topicTypeList, result.getContent()) ;
				}else{
					topicList = result.getContent() ;
				}
				ChatMessageRepository chatMessageRes = UKDataContext.getContext().getBean(ChatMessageRepository.class) ;
				message.setCorrect(false);
				if(topicList.size() > 0){
					
					Topic topic = result.getContent().get(0) ;
					
					message.setMatchnum((int) result.getTotalElements());
					message.setTopicatid(topic.getId());
					message.setTopictitle(topic.getTitle());
					message.setTopic(true);
					message.setCorrect(true);
					
					retChatMessage = new ChatMessage();
					if(topic.isStaticagent()) {
						retChatMessage.setStaticagent(true);
					}
					if(topic!= null && topic.isBussop() && !StringUtils.isBlank(topic.getBusslist())) {
						AiUtils.processAiUserNames(message.getMessage(), topic.getBusslist(), topic.isBussop(), aiUser);
					}
					retChatMessage.setMessage(topic.getContent());
					retChatMessage.setAppid(message.getAppid());
					retChatMessage.setUserid(message.getUserid());
					retChatMessage.setUsername("小E");
					retChatMessage.setChannel(message.getChannel());
					if(topic.isEnablecc() && !StringUtils.isBlank(topic.getCctype())) {
						retChatMessage.setCode(topic.getCctransnum());
						retChatMessage.setBustype(topic.getCctype());
						/**
						 * 只返回文本内容
						 */
						retChatMessage.setMessage(Jsoup.parse(topic.getContent()).text());
					}else {
						retChatMessage.setType(message.getType());
					}
					retChatMessage.setContextid(message.getContextid());
					retChatMessage.setOrgi(message.getOrgi());
					
					if(message.isDebug()) { 
						retChatMessage.setExpmsg(boolQueryBuilder.toString() + "\r\n" + UKTools.toJson(aiUser.getNames()));
					}

					/**
					 * 命中结果，记录日志，记录DEBUG信息，下个版本增加功能
					 */
					retChatMessage.setTopic(true);
					retChatMessage.setTopicid(topic.getId());
					retChatMessage.setTopicatid(topic.getCate());
					
					/**
					 * 推荐多条知识，推荐方式：
					 * 1、命中的知识置信度过低，直接显示推荐提示
					 * 2、命中的知识置信度足够，首条知识作为命中结果
					 * 3、只命中了一条知识，直接返回首条知识作为命中结果
					 * 4、首条知识有推荐知识，则直接返回推荐知识结果
					 */
					if(!StringUtils.isBlank(topic.getRelevance())) { 
						retChatMessage.setSuggestmsg(topic.getRelevance());
						List<String> ids = new ArrayList<String>();
						for(OtherMessageItem item : retChatMessage.getSuggest()) {
							ids.add(item.getId()) ;
						}
						List<OtherMessageItem> otherMessageList = new ArrayList<OtherMessageItem>();
						Iterable<Topic> tempList = topicRes.findByIdInAndOrgi(ids,message.getOrgi()) ;
						for(Topic temp : tempList) {
							if((temp.getBegintime() == null || temp.getBegintime().getTime() < System.currentTimeMillis()) && (temp.getEndtime() == null || temp.getEndtime().getTime() > System.currentTimeMillis())) {
								OtherMessageItem otherMessageItem = new OtherMessageItem();
								otherMessageItem.setTitle(temp.getTitle());
								otherMessageItem.setId(temp.getId());
								otherMessageItem.setMsgtype(UKDataContext.MediaTypeEnum.TEXT.toString());
								
								otherMessageList.add(otherMessageItem) ;
							}
						}
						if(otherMessageList.size() > 0) {
							retChatMessage.setSuggestmsg(UKTools.toJson(otherMessageList));
						}
					}else if(topicList.size() > 1 && aiConfig.isEnablesuggest()) {
						List<OtherMessageItem> otherMessageList = new ArrayList<OtherMessageItem>();
						for(int i=1 ; i<topicList.size() ; i++) {
							Topic temp = topicList.get(i) ;
							boolean exist = false;
							for(OtherMessageItem tempOther  :otherMessageList) {
								if(tempOther.getTitle().equals(temp.getTitle())) {
									exist = true;
									break;
								}
							}
							if(exist == false) {
								OtherMessageItem otherMessageItem = new OtherMessageItem();
								otherMessageItem.setTitle(temp.getTitle());
								otherMessageItem.setId(temp.getId());
								/**
								 * 不返回知识内容正文，避免返回的消息结果过大
								 */
//							otherMessageItem.setContent(temp.getContent());
								otherMessageItem.setMsgtype(UKDataContext.MediaTypeEnum.TEXT.toString());
								otherMessageList.add(otherMessageItem) ; 
							}
						}
						if(otherMessageList.size() > 0) {
							retChatMessage.setSuggestmsg(objectMapper.writeValueAsString(otherMessageList));
							
							if(aiConfig.isEnablesuggest() && !StringUtils.isBlank(aiConfig.getOthersuggestmsg())) {
								retChatMessage.setMessage(retChatMessage.getMessage() + aiConfig.getOthersuggestmsg());
							}
						}
					}
					
					if(topic.isAccept()) {
						aiMroundsProcesser.process(aiUser, message, topic.getId());
					}
				}
				{
					message.setExpmsg(strb.toString() + boolQueryBuilder.toString());
					if (message.getTagget()!=0) {
						message.setTagget(message.isCorrect()?1:2);
					}
					chatMessageRes.save(message) ;
				}
				
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return retChatMessage;
	}
	/**
	 * 
	 * @param orgi
	 * @param aiid
	 * @return
	 */
	private BoolQueryBuilder createSearchQuery(String orgi , String aiid) {
		BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery() ;
		boolQueryBuilder.must(QueryBuilders.termQuery("orgi", orgi));
		if(!StringUtils.isBlank(aiid)) {
			boolQueryBuilder.must(QueryBuilders.termQuery("aiid", aiid)) ;
		}else {
			boolQueryBuilder.must(QueryBuilders.termQuery("aiid", UKDataContext.UKEFU_SYSTEM_NO_AI_CONFIG)) ;
		}
		return boolQueryBuilder ;
	}
	/**
	 * 
	 * @param words
	 * @return
	 */
	private boolean hasKeyWord(String[] words) {
		boolean signal = false ;
		for(String word : words) {
			if(word.length() > 1) {
				signal = true ; break ;
			}
		}
		return signal ;
	}
}
